
package HibernateLayer;

import POJOs.SSessionAllocation;
import POJOs.SCRUDBasic;
import java.lang.reflect.ParameterizedType;
import java.sql.Timestamp;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

/**
 *
 * @author fabiofurlan
 */
public abstract class VCRUDBasicServices<STRUCT extends SCRUDBasic> implements Observer {

    //TODO UNIFY SESSION OPEN AND SESSION CLOSE

    SessionFactory sessionFactory;
    Session sessionBean;
    SSessionAllocation sessionAllocation;
    boolean isValid=true;
    VSessionAllocationServices allocationService;
    Class<STRUCT> type=getTypeClass();

    public VCRUDBasicServices(String mappingsPackagePath){

    }

    public VCRUDBasicServices(){
    }

    public void update(Observable arg0, Object arg1) {
       this.isValid=false;
    }


    protected void checkValidity() throws SessionExausedExcepion{

        if(!this.isValid){
            throw new SessionExausedExcepion();
        }
        else{
            //Updating timestamp
            sessionAllocation.setLastAccess(new Timestamp(System.currentTimeMillis()));
            allocationService.update(sessionAllocation.getId(), sessionAllocation);
        }

    }

    
    public boolean createBasicStructure(STRUCT s) throws SessionExausedExcepion{

        Transaction trx=sessionBean.beginTransaction();
        System.out.println("VCRUDBasicServices | createBasicStructure | Session-Transaction init.......DONE");

        try{
            this.checkValidity();
            sessionBean.save(s);
            trx.commit();
            return true;
        }

        catch(HibernateException ex){
            ex.printStackTrace();
            trx.rollback();
            return false;
        }
    }


     public List<STRUCT> list() throws SessionExausedExcepion{

        Transaction trx=sessionBean.beginTransaction();
        System.out.println("VCRUDBasicServices | list | Session-Transaction init.......DONE");

        try{
            this.checkValidity();
            List cdList=sessionBean.createQuery("from "+this.type.getName()+" c").list();
            trx.commit();
            return cdList;
        }

        catch(HibernateException ex){
            ex.printStackTrace();
            trx.rollback();
            return null;
        }
    }

    public STRUCT simpleIDFinder(int id) throws SessionExausedExcepion{

        Transaction trx=sessionBean.beginTransaction();
        System.out.println("VCRUDBasicServices | simpleIDFinder | Session-Transaction init.......DONE");

        try{
            this.checkValidity();
            STRUCT returnValue=(STRUCT)sessionBean.get(type, id);
            trx.commit();
            return  returnValue;
        }

        catch(HibernateException ex){
            ex.printStackTrace();
            trx.rollback();
            return null;
        }
    }

    public Boolean update(int id, STRUCT toUpdate) throws SessionExausedExcepion{
        Transaction trx=sessionBean.beginTransaction();
        System.out.println("VCRUDBasicServices | update | Session-Transaction init.......DONE");

        try{
            this.checkValidity();
            STRUCT valToUpdate=(STRUCT)sessionBean.get(type, id);
            valToUpdate=toUpdate;
            trx.commit();
            return new Boolean(true);
        }

        catch(HibernateException ex){
            ex.printStackTrace();
            trx.rollback();
            return new Boolean(false);
        }
    }

    public Boolean delete(int id) throws SessionExausedExcepion{
        Transaction trx=sessionBean.beginTransaction();
        System.out.println("VCRUDBasicServices | delete | Session-Transaction init.......DONE");

        try{
            this.checkValidity();
            STRUCT valToDelete=(STRUCT)sessionBean.get(type, id);
            sessionBean.delete(valToDelete);
            trx.commit();
            return new Boolean(true);
        }
        catch(HibernateException ex){
            ex.printStackTrace();
            trx.rollback();
            return new Boolean(false);
        }
    }

    //http://nileshk.com/node/66 there is an example of
    //general parameter reflaction, but this example doesn't work propertly
    //TODO: using reflaction.
    protected abstract Class<STRUCT> getTypeClass();

}
